package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.wordmemorize.converter.ReviewConverter;
import com.cskaoyan.wordmemorize.dao.entity.UserCheckinStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserRevStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocRevDO;
import com.cskaoyan.wordmemorize.dao.mapper.UserCheckinStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserRevStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocRevMapper;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.DownLoadUserReviewDTO;
import com.cskaoyan.wordmemorize.dto.app.UserReviewStatisticsDTO;
import com.cskaoyan.wordmemorize.dto.app.UserVocRevDTO;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserReviewDataCommand;
import com.cskaoyan.wordmemorize.request.UserReviewStatisticsCommand;
import com.cskaoyan.wordmemorize.request.UserVocRevCommand;
import com.cskaoyan.wordmemorize.service.UserReviewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserReviewServiceImpl extends ServiceImpl<UserVocRevMapper, UserVocRevDO> implements UserReviewService {

    @Autowired
    UserRevStatisticsMapper userRevStatisticsMapper;

    @Autowired
    ReviewConverter reviewConverter;

    @Autowired
    UserCheckinStatisticsMapper userCheckinStatisticsMapper;

    // 添加用户的单词复习数据(参数为用户已选单词的id集合)
    // 这个方法只负责在用户点击“加入记忆”时，向user_voc_rev表添加一条新的复习数据（即“已选未学”）
    @Override
    public void addUserRovRev(List<Long> vocIds, Long userId) {
        if (vocIds == null || vocIds.isEmpty()) {
            return;
        }
        // 批量插入用户复习数据（user_voc_rev表），避免重复添加
        for (Long vocId : vocIds) {
            // 判断是否已存在
            Long count = this.count(
                    new LambdaQueryWrapper<UserVocRevDO>()
                            .eq(UserVocRevDO::getUserId, userId)
                            .eq(UserVocRevDO::getVocId, vocId)
            );
            if (count == 0) {
                UserVocRevDO rev = new UserVocRevDO();
                rev.setUserId(userId);
                rev.setVocId(vocId);
                rev.setType(0); // 已选未学
                rev.setReviewInterval(1); // 初始复习间隔
                rev.setFactor(1.4); // 默认易度因子
                rev.setTotalReview(0); // 总复习次数
                rev.setConsecutiveFailCount(0); // 连续失败次数
                // familiarity、nextReviewDate 可不设置
                this.save(rev);
            }
        }
    }


    // 下载用户的所有单词复习数据
    @Override
    public DownLoadUserReviewDTO downloadUserReviewData(PageRequest pageRequest, Long userId) {
        // 1. 分页查询用户的单词复习数据（user_voc_rev表）
        // 构造分页对象，pageNum为当前页码，count为每页条数
        Page<UserVocRevDO> page = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
        // 只查当前用户
        LambdaQueryWrapper<UserVocRevDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserVocRevDO::getUserId, userId);
        // 分页查询
        Page<UserVocRevDO> userVocRevPage = this.page(page, wrapper);

        // 2. 分页查询用户的复习统计数据（user_rev_statistics表）
        Page<UserRevStatisticsDO> statPage = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
        LambdaQueryWrapper<UserRevStatisticsDO> statWrapper = new LambdaQueryWrapper<>();
        statWrapper.eq(UserRevStatisticsDO::getUserId, userId);
        // 分页查询
        Page<UserRevStatisticsDO> userRevStatisticsPage = userRevStatisticsMapper.selectPage(statPage, statWrapper);

        // 3. 用MapStruct转换DO为DTO并封装分页结果
        // 单词复习数据分页DO转DTO
        PageDTO<UserVocRevDTO> userVocRevPageDTO = reviewConverter.userVocRevPage2PageDTO(
                userVocRevPage.getRecords(), userVocRevPage.getTotal());
        // 复习统计数据分页DO转DTO
        PageDTO<UserReviewStatisticsDTO> userReviewStatisticsPageDTO = reviewConverter.userRevStatistcsPage2PageDTO(
                userRevStatisticsPage.getRecords(), userRevStatisticsPage.getTotal());

        // 4. 封装返回对象
        DownLoadUserReviewDTO dto = new DownLoadUserReviewDTO();
        // 设置单词复习数据分页
        dto.setUserVocRevPage(userVocRevPageDTO);
        // 设置复习统计数据分页
        dto.setUserReviewStatisticsPage(userReviewStatisticsPageDTO);

        // 5. 返回结果
        return dto;
    }



    // 同步用户的复习数据（即上传用户复习数据并更新）需要完成以下工作：
    // 更新 user_voc_rev 表：对上传的每条单词复习数据，找到对应的 user_voc_rev 记录并 update。
    // 更新/插入 user_rev_statistics 表：对上传的每条复习统计数据，找到对应的 user_rev_statistics 记录并 update（或 insert）。
    // 更新 user_checkin_statistics 的 totalTime 字段：将本次上传的所有复习统计数据的学习时长累加到用户的总学习时长。
    @Override
    public void synchronizeUserReviewData(UserReviewDataCommand command, Long userId) {
        // 1. 更新该用户所有已选单词的复习记录（user_voc_rev表）
        // 获取前端上传的单词复习数据命令列表
        List<UserVocRevCommand> userVocRevCommands = command.getVocRevCommands();
        // 用 MapStruct 转换器将命令对象转为 DO 对象
        List<UserVocRevDO> userVocRevList = userVocRevCommands.stream()
                .map(reviewConverter::userVocRevCommand2DO)
                .toList();
        if (!userVocRevList.isEmpty()) {
            // 补充 userId，确保每条记录归属于当前用户
            userVocRevList.forEach(userVocRevDO -> userVocRevDO.setUserId(userId));
            // 批量更新（根据id更新），如果id不存在会报错，前端需保证传递的id为已存在记录
            this.updateBatchById(userVocRevList);
        }

        // 2. 更新/插入复习统计数据（user_rev_statistics表）
        // 获取前端上传的复习统计数据命令对象
        UserReviewStatisticsCommand revStatisticsCommand = command.getRevStatisticsCommand();
        if (revStatisticsCommand != null) {
            // 用 MapStruct 转换器将命令对象转为 DO 对象
            UserRevStatisticsDO userRevStatisticsDO = reviewConverter
                    .userRevStatisticsCommand2DO(revStatisticsCommand);
            userRevStatisticsDO.setUserId(userId);

            // 查询当天是否已有统计记录（保证一天只有一条统计数据）
            UserRevStatisticsDO exist = userRevStatisticsMapper.selectOne(
                    new LambdaQueryWrapper<UserRevStatisticsDO>()
                            .eq(UserRevStatisticsDO::getUserId, userId)
                            .eq(UserRevStatisticsDO::getReviewDate, userRevStatisticsDO.getReviewDate())
            );
            if (exist != null) {
                // 已有记录则更新（保持id不变）
                userRevStatisticsDO.setId(exist.getId());
                userRevStatisticsMapper.updateById(userRevStatisticsDO);
            } else {
                // 没有则插入新记录
                userRevStatisticsMapper.insert(userRevStatisticsDO);
            }

            // 3. 更新 user_checkin_statistics 的 totalTime 字段（累加本次学习时长）
            if (userRevStatisticsDO.getStudyTime() != null) {
                UserCheckinStatisticsDO checkinStat = userCheckinStatisticsMapper.selectOne(
                        new LambdaQueryWrapper<UserCheckinStatisticsDO>()
                                .eq(UserCheckinStatisticsDO::getUserId, userId)
                );
                if (checkinStat != null) {
                    // 取原有总时长（为null时视为0），累加本次学习时长
                    Long oldTotalTime = checkinStat.getTotalTime() == null ? 0L : checkinStat.getTotalTime();
                    Long newTotalTime = oldTotalTime + userRevStatisticsDO.getStudyTime();
                    checkinStat.setTotalTime(newTotalTime);
                    userCheckinStatisticsMapper.updateById(checkinStat);
                }
            }
        }
    }


}
